// 有序块的存放位置
// R 81~96 S 132~163
// 连接块的输出位置250~332
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include "extmem.h"
#include "t2.h"
#include "t4.h"
// main 在需要完成该道问题时启用，其他时候隐藏用以做库
// int main(int argc, char const *argv[])
// {
//     Buffer buf;
//     if (!initBuffer(520, 64, &buf))
//     {
//         perror("Buffer Initialization Failed!\n");
//         return -1;
//     }
//     joinR_S(&buf,81,132,16,32,250);
//     printf("\nBuf IO num:%ld\n",buf.numIO);
//     return 0;
// }

void writeData2(int rp,int *wp,unsigned char *rblk,unsigned char *w1,int *wf,Buffer *buf)
{
   
    // 将整个元组的数据复制到写出block
    for (int i = 0; i < 8; i++)
    {
        *(w1+*wp)=*(rblk+rp);
        (*wp)++;
        rp++;
    }
    if (*wp==56)
    {
        // printf("write %d to the disk\n",++wcount);
        //将下一个块的指针存入p=57中，并将当前块的数据写入磁盘块中，清空当前块
        char next[5];
        itoa((*wf)+1,next);
        // printf("\nis here?%s\n",next);
        int t=0;
        while (next[t]!='\0')
        {
            *(w1+*wp)=next[t];
            (*wp)++;
            t++;
        }
        
        
        if (writeBlockToDisk(w1, (*wf)++, buf) != 0)
        {
            perror("Writing Block Failed!\n");
            exit(-1);
        }
        w1 = getNewBlockInBuffer(buf);
        // 重新从0开始写数据，就相当于使用了free
        // api里的free相当于告知buf当前块已不再需要使用
        *wp=0;
    }
}

void joinR_S(Buffer *buf,int RBlkNo,int SBlkNo,int Rlength,int Slength,int wf)
{
    int Rlast=RBlkNo+Rlength-1;
    int Slast=SBlkNo+Slength-1;
    unsigned char *Rbuf=readBlockFromDisk(RBlkNo++,buf);
    unsigned char *Sbuf=readBlockFromDisk(SBlkNo++,buf);
    unsigned char *wbuf=getNewBlockInBuffer(buf);
    int wp=0;
    int count=0;
    int rp,sp;
    int RX,SX;
    int RY,SY;
    // int ovR,ovS;
    rp=sp=0;
    getValueByp(&RX,&RY,rp,Rbuf);
    getValueByp(&SX,&SY,sp,Sbuf);
    // 当有一个关系读完的时候，join操作就做完了
    // while (!ovR && !ovS)
    while(1)
    {
        if (RX>SX)
        {
            sp+=8;
            if (sp==56)
            {
                sp=0;
                freeBlockInBuffer(Sbuf,buf);
                if (SBlkNo<=Slast)
                {
                    Sbuf=readBlockFromDisk(SBlkNo++,buf);
                }
                else
                {
                    // 别忘了在缓冲区还有数据的时候清空缓存区
                    if (wp!=0)
                    {
                        memset(wbuf+wp,0,sizeof(char)*64-wp);
                        writeBlockToDisk(wbuf,wf,buf);
                    }
                    return;
                }
            }
            getValueByp(&SX,&SY,sp,Sbuf);
        }
        else if (RX<SX)
        {
            rp+=8;
            if (rp==56)
            {
                rp=0;
                freeBlockInBuffer(Rbuf,buf);
                if (RBlkNo<=Rlast)
                {
                    Rbuf=readBlockFromDisk(RBlkNo++,buf);
                }
                else
                {
                    if (wp!=0)
                    {
                        memset(wbuf+wp,0,sizeof(char)*64-wp);
                        writeBlockToDisk(wbuf,wf,buf);
                    }
                    return;
                }
            }
            getValueByp(&RX,&RY,rp,Rbuf);
        }
        else
        {
            int sp_pre=sp;
            int SBlkNo_pre=SBlkNo-1;
            do
            {
                // 用于标注此时SBuf是否存在
                int sflag=1;
                do
                {
                    printf("-----------------------");
                    printf("\ncount:%d",++count);
                    printf("\nRBlk:%d,rp:%d\n",RBlkNo-1,rp);
                    printf("\nRX:%d RY:%d\n",RX,RY);
                    printf("\nSBlk:%d,sp:%d\n",SBlkNo-1,sp);
                    printf("\nSX:%d SY:%d\n",SX,SY);

                    writeData2(rp,&wp,Rbuf,wbuf,&wf,buf);
                    writeData2(sp,&wp,Sbuf,wbuf,&wf,buf);
                    sp+=8;
                    if (sp==56)
                    {
                        sp=0;
                        freeBlockInBuffer(Sbuf,buf);
                        sflag=0;
                        if (SBlkNo<=Slast)
                        {
                            Sbuf=readBlockFromDisk(SBlkNo++,buf);
                            sflag=1;
                        }
                        else
                        {
                            break;
                        }
                    }
                    getValueByp(&SX,&SY,sp,Sbuf);
                } while (SX==RX);
                if (sflag)
                {
                    freeBlockInBuffer(Sbuf,buf);
                }
                // 回位
                SBlkNo=SBlkNo_pre;
                Sbuf=readBlockFromDisk(SBlkNo++,buf);
                sp=sp_pre;
                rp+=8;
                if (rp==56)
                {
                    rp=0;
                    freeBlockInBuffer(Rbuf,buf);
                    if (RBlkNo<Rlast)
                    {
                        Rbuf=readBlockFromDisk(RBlkNo++,buf);
                    }
                    else
                    {
                        if (wp!=0)
                        {
                            memset(wbuf+wp,0,sizeof(char)*64-wp);
                            writeBlockToDisk(wbuf,wf,buf);
                        }
                        return;
                    }
                }
                // 回位后要重新get一遍
                getValueByp(&SX,&SY,sp,Sbuf);
                getValueByp(&RX,&RY,rp,Rbuf);
            } while (RX==SX);
        }
        
        
    }
    
}
